/* eslint-disable @typescript-eslint/no-unused-expressions */
import type {
  AxiosRequestConfig,
  AxiosInstance,
  AxiosResponse,
  InternalAxiosRequestConfig
} from 'axios'

import axios from 'axios'
import { AxiosCanceler } from './axiosCancel'
import { isFunction } from '@/utils/is'
import { deepClone } from '@/utils/'

import type { RequestOptions, CreateAxiosOptions, Result } from './types'
import { storage } from '@/utils/Storage'

export * from './axiosTransform'

/**
 * @description:  axios模块
 */
function processIpAndParam(ip: string, param: string | undefined): string {
  // const param = storage.get('userId')
  // 去掉 IP 中的点号，并将其转换为数字
  const ipWithoutDots: number = Number(ip.replace(/\./g, ''))

  // 计算点号的位置（1-based index），并将其合并成一个数字
  const dotCount: string = ip.split('').reduce((acc, char, index) => {
    if (char === '.') {
      acc += index.toString() // 索引位置从1开始
    }
    return acc
  }, '')

  // 判断 param 的类型，并进行相应的处理
  let paramToAdd: number = 0

  if (param) {
    // 如果 param 是数字字符串，则转为数字并相加
    if (!isNaN(Number(param))) {
      paramToAdd = Number(param)
    } else {
      // 如果 param 是普通字符串，直接加上 10000
      paramToAdd = 10000
    }
  }

  // 数值相加
  const sum: number = ipWithoutDots + paramToAdd

  // 拼接结果：相加后的值 + dotCount（点号的位置数字）
  const result: string = `${sum}${dotCount}`
  return result
}

async function getCachedIp(): Promise<string> {
  const cacheKey = 'cached_ip'
  const cacheExpireKey = 'cached_ip_expire'

  // 检查缓存是否存在且未过期
  const cachedIp = localStorage.getItem(cacheKey)
  const cachedExpire = localStorage.getItem(cacheExpireKey)

  if (cachedIp && cachedExpire && Date.now() < Number(cachedExpire)) {
    return cachedIp // 返回缓存的 IP
  }

  // 如果缓存不存在或已过期，重新请求 IP
  try {
    const response = await fetch('https://api.ipify.org?format=json')
    const data = await response.json()
    const ip = data.ip

    // 更新缓存，设置缓存有效期为 1 小时
    const expireTime = Date.now() + 8 * 60 * 60 * 1000 // 1 小时
    localStorage.setItem(cacheKey, ip)
    localStorage.setItem(cacheExpireKey, expireTime.toString())

    return ip
  } catch (error) {
    console.error('Failed to fetch IP:', error)
    return '' // 返回空字符串，表示 IP 获取失败
  }
}
export class VAxios {
  private axiosInstance: AxiosInstance
  private options: CreateAxiosOptions

  constructor(options: CreateAxiosOptions) {
    this.options = options

    this.axiosInstance = axios.create(options)
    this.setupInterceptors()
  }

  /**
   * @description:  创建axios实例
   */
  private createAxios(config: CreateAxiosOptions): void {
    this.axiosInstance = axios.create(config)
  }

  private getTransform() {
    const { transform } = this.options
    return transform
  }

  getAxios(): AxiosInstance {
    return this.axiosInstance
  }

  /**
   * @description: 重新配置axios
   */
  configAxios(config: CreateAxiosOptions) {
    if (!this.axiosInstance) {
      return
    }
    this.createAxios(config)
  }

  /**
   * @description: 设置通用header
   */
  setHeader(headers: any): void {
    if (!this.axiosInstance) {
      return
    }
    Object.assign(this.axiosInstance.defaults.headers, headers)
  }

  /**
   * @description: 拦截器配置
   */
  private setupInterceptors() {
    const transform = this.getTransform()
    if (!transform) {
      return
    }
    const {
      requestInterceptors,
      requestInterceptorsCatch,
      responseInterceptors,
      responseInterceptorsCatch
    } = transform

    const axiosCanceler = new AxiosCanceler()

    // 请求拦截器配置处理
    this.axiosInstance.interceptors.request.use(async (config: InternalAxiosRequestConfig<any>) => {
      const { headers: { ignoreCancelToken } = { ignoreCancelToken: false } } = config
      !ignoreCancelToken && axiosCanceler.addPending(config)
      // 获取最新的 userId 和 IP 地址
      const param = storage.get('userId')
      const ip = await getCachedIp();
      // const t = processIpAndParam(ip, param) // 计算 t 值

      // 创建符合 AxiosRequestHeaders 类型的 headers 对象

      const headers: any = {
        ...config.headers,
        t: ip // 添加动态计算的 t 值
      }

      config.headers = headers
      if (requestInterceptors && isFunction(requestInterceptors)) {
        // eslint-disable-next-line no-param-reassign
        config = requestInterceptors(config) as InternalAxiosRequestConfig<any>
      }
      return config
    }, undefined)

    // 请求拦截器错误捕获
    requestInterceptorsCatch &&
      isFunction(requestInterceptorsCatch) &&
      this.axiosInstance.interceptors.request.use(undefined, requestInterceptorsCatch)

    // 响应结果拦截器处理
    this.axiosInstance.interceptors.response.use((res: AxiosResponse<any>) => {
      res && axiosCanceler.removePending(res.config)
      if (responseInterceptors && isFunction(responseInterceptors)) {
        // eslint-disable-next-line no-param-reassign
        res = responseInterceptors(res)
      }
      return res
    }, undefined)

    // 响应结果拦截器错误捕获
    responseInterceptorsCatch &&
      isFunction(responseInterceptorsCatch) &&
      this.axiosInstance.interceptors.response.use(undefined, responseInterceptorsCatch)
  }
  //
  // /**
  //  * @description:  文件上传
  //  */
  // uploadFiles(config: AxiosRequestConfig, params: File[]) {
  //   const formData = new FormData();
  //
  //   Object.keys(params).forEach((key) => {
  //     formData.append(key, params[key as any]);
  //   });
  //
  //   console.log(config)
  //
  //
  //   const url = `${process.env.REACT_APP_BASE_URL}${config.url}`
  //
  //   return this.axiosInstance.post(url,formData,{
  //     headers: {
  //       'Content-type': ContentTypeEnum.FORM_DATA,
  //     }
  //   })
  // }

  /**
   * @description:   请求方法
   */
  request<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
    let conf: AxiosRequestConfig = deepClone(config)
    const transform = this.getTransform()

    const { requestOptions } = this.options

    const opt: RequestOptions = Object.assign({}, requestOptions, options)

    const { beforeRequestHook, requestCatch, transformRequestData } = transform || {}
    if (beforeRequestHook && isFunction(beforeRequestHook)) {
      conf = beforeRequestHook(conf, opt)
    }
    return new Promise((resolve, reject) => {
      this.axiosInstance
        .request<any, AxiosResponse<Result>>(conf)
        .then((res: AxiosResponse<Result>) => {
          // 请求是否被取消
          const isCancel = axios.isCancel(res)
          if (
            transformRequestData &&
            isFunction(transformRequestData) &&
            !isCancel &&
            !conf.responseType
          ) {
            const ret = transformRequestData(res, opt)
            // ret !== undefined ? resolve(ret) : reject(new Error('request error!'));
            return resolve(ret)
          }
          resolve(res?.data as unknown as Promise<T>)

          reject(res as unknown as Promise<T>)
        })
        .catch((e: Error) => {
          if (requestCatch && isFunction(requestCatch)) {
            reject(requestCatch(e))
            return
          }
          reject(e)
        })
    })
  }
}
